//***************************************************************************//
//*
//* 内容摘要：线程内部消息队列实现
//*	
//* 当前版本：V1.0		
//* 作    者：zhfayuan
//* 完成日期：2015-12-26
//**************************************************************************//

#if !defined(SDMESSAGE_H)
#define SDMESSAGE_H

#include "SDCommon.h"
#include "SDEvent.h"
#include "SDThread.h"
#include "SDLog.h"

#define MSG_QUEUE_PRI_CNT    4   // 队列中优先级总数

class CSDRanks
{
public:
	CSDRanks(UINT unRankSize);
	virtual ~CSDRanks();

public:
	BOOL GetElement(void **ppack);
	BOOL AddElement(void *pack);
	BOOL IsFull();

private:
	int          m_nMsgQueueLen;
	int          m_nIstPosi;
	int          m_nGetPosi;
	int          m_nMsgCnt;
	void **m_MsgQueue;
};

typedef struct T_Message
{
	int	 nDataBufSize;	 //ucDataBuf的实际大小
	char ucDataBuf[1];   //预分配一个字节
}T_Message;


class CSDMessage
{
public:
	CSDMessage();
	virtual ~CSDMessage();

public:

	BOOL Create(int nMsgQueueLen, const char *pstrName = NULL);
	void Close();

	//接口内部将拷贝传入的消息块并插入处理队列中，外层需要自行负责消息块的释放
	BOOL PostPackMessage(PACK_MESSAGE *pack);
	// 此虚函数为子类去实现，返回假值(0)的时候，消息类自动释放消息块；返回真(非零)时，由子类去控制消息块的释放
	virtual  int ProcessMessage(void* pParam) = 0;

private:
	CSDThread    m_ConsumeThd;
	CSDEvent     m_ProcessEvent;
	void         *m_pvQueue;

	BOOL         m_bClose;
	CSDRanks     *m_QueueArr[MSG_QUEUE_PRI_CNT];

	BOOL         mfGetMessage(PACK_MESSAGE **ppack);
	void         mfClearMessage();
	
	static int  ConsumeMessageThread(void* pParam);
	static int  ConsumeMessageThreadClose(void* pParam);
};


typedef int (*ProcessData)(char* pBuf, void *pObject);

class CSDThreadProcessData  : public CSDMessage
{
public:
	CSDThreadProcessData(ProcessData pFuc, void *pObject)
	{
		if (!Create(100, "ThreadProcessData"))
		{
			SDLOG_PRINTF("common", SD_LOG_LEVEL_ERROR, "CSDThreadProcessData create CSDMessage fail..");
			m_fucProcessFuction = NULL;
			m_pObject = NULL;
		}
		else
		{
			m_fucProcessFuction = pFuc;
			m_pObject = pObject;
		}
	}
	virtual ~CSDThreadProcessData()
	{
		CSDMessage::Close();
	}
public:
	int ProcessMessage(void* pParam)
	{
		if (m_fucProcessFuction != NULL)
		{
			return (*m_fucProcessFuction)((char*)pParam, m_pObject);
		}
		else
			return 0;
	}

private:
	ProcessData   m_fucProcessFuction;
	void          *m_pObject;
};



class CSDMessage2
{
public:
	CSDMessage2();
	virtual ~CSDMessage2();
	
public:
	BOOL Create(int nMsgQueueLen, const char *pstrName = NULL);
	void Close();

	//接口内部将拷贝传入的消息块并插入处理队列中，外层需要自行负责消息块的释放
	BOOL PostPackMessage(int nLen, void *pData);
	//外层实现消息的真实处理
	virtual  int  ProcessMessage(int nLen, void* pData) = 0;

private:
	CSDThread    m_ConsumeThd;
	CSDEvent     m_ProcessEvent;
	void         *m_pvQueue;

	BOOL         m_bClose;
	CSDRanks     *m_QueueArr;
	int			 m_nMsgQueueLen;

	BOOL        mfGetMessage(void **ppack);
	void		mfClearMessage();

	static int  ConsumeMessageThread(void* pParam);
	static int  ConsumeMessageThreadClose(void* pParam);
};


typedef int (*ProcessDataWithOneObj)(int nLen, char* pBuf, void *pObject);
typedef int (*ProcessDataWithTwoObj)(int nLen, char* pBuf, void *pObject1, void *pObject2);

class CSDThreadProcessData2  : public CSDMessage2
{
public:
	CSDThreadProcessData2(ProcessDataWithOneObj pFuc, void *pObject)
	{
		m_pFucProcessWithTwoObj = NULL;
		m_pObject2 = NULL;

		if (!Create(4096, "CSDThreadProcessData2"))
		{
			SDLOG_PRINTF("common", SD_LOG_LEVEL_ERROR, "CSDThreadProcessData2 create CSDMessage fail..");
			m_pFucProcessWithOneObj = NULL;
			m_pObject1 = NULL;
		}
		else
		{
			m_pFucProcessWithOneObj = pFuc;
			m_pObject1 = pObject;
		}
	}

	CSDThreadProcessData2(ProcessDataWithTwoObj pFuc, void *pObject1, void *pObject2)
	{
		m_pFucProcessWithOneObj = NULL;

		if (!Create(4096, "CSDThreadProcessData2"))
		{
			SDLOG_PRINTF("common", SD_LOG_LEVEL_ERROR, "CSDThreadProcessData2 create CSDMessage fail..");
			m_pFucProcessWithTwoObj = NULL;
			m_pObject1 = NULL;
			m_pObject2 = NULL;
		}
		else
		{
			m_pFucProcessWithTwoObj = pFuc;
			m_pObject1 = pObject1;
			m_pObject2 = pObject2;
		}
	}

	virtual ~CSDThreadProcessData2()
	{
		CSDMessage2::Close();
	}

public:
	int ProcessMessage(int nLen, void* pData)
	{
		if (m_pFucProcessWithOneObj != NULL)
		{
			return (*m_pFucProcessWithOneObj)(nLen, (char*)pData, m_pObject1);
		}
		else if (m_pFucProcessWithTwoObj != NULL)
		{
			return (*m_pFucProcessWithTwoObj)(nLen, (char*)pData, m_pObject1, m_pObject2);
		}
		else
		{
			return 0;
		}
	}
	
	
private:
	ProcessDataWithOneObj   m_pFucProcessWithOneObj;
	ProcessDataWithTwoObj   m_pFucProcessWithTwoObj;
	void           *m_pObject1;
	void           *m_pObject2;
};

#endif // !defined(SDMESSAGE_H)
